package main

import (
	"fmt"
)

type speaker interface {
	// 但凡实现了下列方法的 都算实现了此接口
	speck()
}
type mover interface {
	move()
}
type animal interface {
	speaker // 接口可以嵌套
	mover
}

type cat struct {
	name string
}

func (c cat) speck() {
	fmt.Printf("%s mmm~\n", c.name)
}

type dog struct {
	name string
}

func (d *dog) speck() {
	fmt.Printf("%s www~\n", d.name)
}

func da(x speaker) {
	x.speck()
}

func main() {
	var c1 = cat{"小黑"}
	var d1 = dog{"aaaa"}
	da(&c1) // 小黑 mmm~
	da(c1)  // 小黑 mmm~
	// da(d1) // dog does not implement speaker (speck method has pointer receiver)
	da(&d1) // aaaa www~
	var s1 speaker
	s1 = c1
	fmt.Printf("%#v\n", s1) // main.cat{name:"小黑"}
	// 空接口
	var x interface{}
	x = 144 // 可以存任意类型的变量
	x = "aaa"
	x = cat{"小黄"}
	fmt.Printf("%#v\n", x) // main.cat{name:"小黄"}
	// 类型断言
	res, ok := x.(int)
	// 第二参数返回是否判断正确，如果错误第一参数返回该类型的零值
	fmt.Println(res, ok) // 0 false
	x = "abcde"
	res1, ok1 := x.(string)
	fmt.Println(res1, ok1) // abcde true

	// `x.(type)` 只能用在switch case 中
	switch v := x.(type) {
	case string:
		fmt.Println("isString", v) // isString abcde
	case int:
		fmt.Println("isInt", v)
	default:
		fmt.Println("idk", v)
	}

}
